package util;

import java.util.ArrayList;
import java.util.List;

public class Calculator {

	private final double degreeMetersValue = 111111.00;
	private List<Point> points = new ArrayList<Point>();

	/**
	 * Method that convert from Latitude/Longitude to meters
	 * @param latitude - the latitude to convert
	 * @param longitude - the longitude to convert
	 * @return A point with the coordinates in meters
	 * @throws Exception 
	 */
	public Point convertToMeters(double latitude, double longitude) throws Exception {
		if (latitude > 90 || latitude < -90) {
			throw new Exception ("invalid latitude input");
		}
		if (longitude > 180 || longitude < -180) {
			throw new Exception ("invalid longitude input");
		}
		double x = (degreeMetersValue *Math.cos(latitude)) * longitude;
		double y = (degreeMetersValue *latitude);
		Point point = new Point(Math.abs(x),Math.abs(y));
		return point;
	}

	/**
	 * Calculate area with a given points list
	 * @param points - the points list
	 * @return the area
	 * @throws Exception 
	 */
	public double calculateArea (List<Point> points) throws Exception {
		if (points == null) {
			throw new Exception("The points list is null");
		}
		if (points.size() < 4) {
			throw new Exception("Invalid points list: The list must have at least 4 points");
		}

		double area = 0;
		for (int i = 0; i < points.size() - 1; i++) {
			area += points.get(i).getX()*points.get(i+1).getY();
			area -= points.get(i).getY()*points.get(i+1).getX();
		}
		area /= 2;
		return area;
	}

	/**
	 * Calculate area with the points list
	 * @return the area
	 * @throws Exception 
	 */
	public String calculateArea () throws Exception {
		if (points.size() < 4) {
			throw new Exception("Invalid points list: The list must have at least 4 points");
		}

		double area = 0;
		for (int i = 0; i < points.size() - 1; i++) {
			area += points.get(i).getX()*points.get(i+1).getY();
			area -= points.get(i).getY()*points.get(i+1).getX();
		}
		area /= 2;
		String stringArea = new Double(area).toString();
		if (stringArea.split("E").length > 1) {
			stringArea = removeScientificNotation(stringArea);
		}
		return stringArea;
	}

	/**
	 * Add a point to the points list
	 * @param point
	 * @throws Exception
	 */
	public void addPoints(Point point) throws Exception {
		if (point == null) {
			throw new Exception("The point is null");
		}
		points.add(point);
	}

	/**
	 * Sometimes the double will be in scientific notation, so this method
	 * will transform the double in a number without the notation.
	 * 
	 * Scientific notation is when the number is like 9,121402329 * 10^6
	 * 
	 * @param area
	 * @return
	 */
	public String removeScientificNotation(String area) {
		int a = Integer.parseInt(area.split("E")[1]);
		String[] sA = area.split("");
		String integer = sA[1];
		for(int i = 3; i < a+3; i ++) {
			integer += sA[i];
		}
		String decimal = "";
		for(int i = a+3; i < sA.length-2; i ++) {
			decimal += sA[i];
		}
		Integer i = new Integer("12");
		return integer + "." + decimal;
	}
	
}